#include <sys/types.h>
#include <ctype.h>
#include <pthread.h>
#include <sys/socket.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <getopt.h>

#define MES_STR "Hello world!"

void *thread_worker(void *args);

void print_usage(char *progname)
{
	printf("%s usage: \n", progname);
//	printf("-i(--ipaddr): sepcify server IP address\n");
	printf("-p(--port): sepcify server port\n");
	printf("-h(--help): print this help information\n");

	return;
}

int main(int argc, char** argv)
{
       
	pthread_attr_t  thread_attr;
	pthread_t       tid;
	int             sockfd = -1;
	int             on = 1;
	int             BACKLOG = 1024;
	int             acfd = -1;
	int             rv = -1;
	int             ch = -1;
	socklen_t       cliaddr_len;
//	int             PORT=12345;
//	char            *ID = "192.168.41.1";
	int             PORT=0;
//	char            *ID
	char            buf[1024];
	struct          sockaddr_in serv_addr;
	struct          sockaddr_in cli_addr;
	struct          option opts[] ={
//	       	        {"ipaddr", required_argument,NULL,'i'},
		        {"port", required_argument,NULL,'p'},
		        {"help", no_argument,NULL,'h'},
		        {NULL, 0, NULL, 0}
	};


	while((ch=getopt_long(argc, argv, "i:p:h", opts, NULL)) != -1 )
	{
		switch(ch)
		{
//			case'i':
//				ID=optarg;
				break;
		       	case'p':
                                PORT=atoi(optarg);
                                break;
		       	case'h':
                                print_usage(argv[0]);
                                return 0;
		}
	}
	
	if(/*!ID ||*/ !PORT)
	{
		print_usage(argv[0]);
		return 0;
	}


	sockfd=socket(AF_INET, SOCK_STREAM, 0);
	if(sockfd<0)
	{
		printf("Create socket filetrue: %s\n",strerror(errno));
		return -1;
	}
        printf("Create socket successful: %d\n",sockfd);

	setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));



	memset(&serv_addr, 0, sizeof(serv_addr));
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_port = htons(PORT);
	serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
	
	rv=bind(sockfd,(struct sockaddr*)&serv_addr, sizeof(serv_addr));
	if(rv<0)
	{
                printf("Bind filetrue: %s\n",strerror(errno));
                return -2;
        }
        printf("socket[%d] bind on port[%d] for all IP ok\n",sockfd,PORT);

	listen(sockfd, BACKLOG);
	while(1)
	{
		printf("Start waitting for accept new client...\n");
		cliaddr_len = sizeof(cli_addr);
		acfd=accept(sockfd, (struct sockaddr*)&cli_addr,&cliaddr_len);
		if(acfd<0)
		{
			printf("Accept new cilent filetrue: %s\n",strerror(errno));
                        return -3;
                }
	     
		printf("accept new client[%d:%d] on port[%d]\n",cli_addr.sin_addr.s_addr, cli_addr.sin_port, PORT);
		printf("acfd: %d\n",acfd);
	      
	
	
		if( pthread_attr_init(&thread_attr))
	       	{
		       	printf("pthread_attr_init failure:%s\n",strerror(errno));
                        return -1;
                }

                if(pthread_attr_setstacksize(&thread_attr, 120*1024))
                {
                        printf("pthread_attr_setstacksize failure:%s\n",strerror(errno));
                        return -2;
                }

                if(pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED))
                {
                        printf("pthread_attr_setdetachstate failure:%s\n",strerror(errno));
                        return -3;
                }

               // pthread_attr_destroy(&thread_attr);
	       if(pthread_create(&tid, &thread_attr, thread_worker, (void *)(long)acfd))
	       {
		       printf("pthread_create failure:%s\n",strerror(errno));
		       return -4;
	       }
                printf("pthread_create thread_work:%ld successful!\n",tid);
                pthread_attr_destroy(&thread_attr);
		pthread_join(tid,NULL);
	}
	close(sockfd);
	return 0;
	
}
     


void *thread_worker(void *args)	
{

	struct    sockaddr_in cli_addr;
	int       rv = -1;
	char      buf[1024];
	int       acfd = -1;


	acfd=(int)(long)args;

	if(!args)
	{
		printf("Invalid input arguments in %s()\n", __FUNCTION__);
		close(acfd);
		pthread_exit(NULL);

	}
	printf("Start conmmunication to client...\n");

	while(1)
	{

		memset(&buf, 0, sizeof(buf));
		rv=read(acfd, buf, sizeof(buf));
                if(rv<0)
                {
                        printf("Read from client [%d:%d] filetrue: %s\n",cli_addr.sin_addr.s_addr,cli_addr.sin_port,strerror(errno));
                        close(acfd);
                        pthread_exit(NULL);
                }
                else if(rv==0)
                {
                        printf("Client connect to server get disconnect!\n");
                        close(acfd);
                        pthread_exit(NULL);
                }
		else
		{
			printf("read from client data:%d\n",rv);
                        printf("Read from client:%s\n",buf);  
		}

		rv=write(acfd,MES_STR, strlen(MES_STR));
		printf("rv:%d\n",rv);
		if(rv<0)
                {
		    	printf("Write to client[%d:%d] filetrue: %s\n",cli_addr.sin_addr.s_addr,cli_addr.sin_port,strerror(errno));
			close(acfd);
                        pthread_exit(NULL);
                }
	       	printf("write to client data:%d\n",rv);

    /*     	memset(&buf, 0, sizeof(buf));
        	rv=read(acfd, buf, sizeof(buf));
        	if(rv<0)
                {
                        printf("Read from client [%d:%d] filetrue: %s\n",cli_addr.sin_addr.s_addr,cli_addr.sin_port,strerror(errno));
			close(acfd);
                        pthread_exit(NULL);
                }
		else if(rv==0)
                {
                        printf("Client connect to server get disconnect!\n");
			close(acfd);
         		pthread_exit(NULL);
                }
		printf("read from client data:%d\n",rv);
		printf("Read from client:%s\n",buf);   */  
	}
	close(acfd);
//	return (NULL);
        pthread_exit(NULL);
}












